﻿using System;
using System.Linq;
using System.Collections.Generic;
using System.ComponentModel;
using System.ComponentModel.DataAnnotations;

namespace IceTea.Domain.Models
{
    [MetadataType(typeof(UserMetaData))]
    public partial class User : IValidatableObject
    {
        public User()
        {
            this.SuperAdmin = false;
        }

        #region MetaData
        public class UserMetaData
        {
            [System.Web.Mvc.HiddenInput(DisplayValue=false)]
            public int Id { get; set; }

            [Display(Name="User Name", Prompt="Please enter user name")]
            [Required(ErrorMessage="Please enter the user name")]
            [DisplayFormat(ConvertEmptyStringToNull=false)]
            public string UserName { get; set; }

            [Display(Name="Email Address")]
            [DataType(DataType.EmailAddress)]
            [Required(ErrorMessage="Please enter the Email address")]
            [RegularExpression(".+\\@.+\\..+", ErrorMessage = "Please enter a valid Email address")]
            [DisplayFormat(ConvertEmptyStringToNull=false)]
            public string Email { get; set; }

            [Display(Name="Full Name")]
            [DataType(DataType.Text)]
            [Required(ErrorMessage="Please enter the full name")]
            [DisplayFormat(ConvertEmptyStringToNull=false)]
            public string FullName { get; set; }

            [Display(Name="Title")]
            [DataType(DataType.Text)]
            [DisplayFormat(ConvertEmptyStringToNull=false)]
            public string Title { get; set; }

            [Display(Name="Is Administrator?")]
            [UIHint("Boolean")]
            public bool SuperAdmin { get; set; }

            [Display(Name="Password Question")]
            [DisplayFormat(ConvertEmptyStringToNull=false)]
            public string PasswordQuestion { get; set; }

            [Display(Name="Password Answer")]
            [DisplayFormat(ConvertEmptyStringToNull=false)]
            public string PasswordAnswer { get; set; }
        }
        #endregion

        [Display(Name="Password")]
        [Required(ErrorMessage="Please enter password")]
        [DataType(DataType.Password)]
        [StringLength(50, MinimumLength=6, ErrorMessage="Your password length must not less than 6")]
        [DisplayFormat(ConvertEmptyStringToNull=false)]
        public string Password1 { get; set; }

        [Display(Name="Retype Password")]
        [DataType(DataType.Password)]
        [Compare("Password1", ErrorMessage="You need repeat the password consistent with the first one")]
        [DisplayFormat(ConvertEmptyStringToNull=false)]
        public string Password2 { get; set; }

        #region public static methods
        //create an new user
        public static bool CreateNewUser(User user)
        {
            user.Password = SecurityHelper.HashPassword(user.Password1);
            user.CreationDate = DateTime.Now;

            using (IceTeaEntities ite = new IceTeaEntities())
            {
                ite.AddToUsers(user);
                if (ite.SaveChanges() > 0)
                    return true;
            }
            return false;
        }

        //retrieve the specified user
        public static User RetrieveUser(string username)
        {
            if (string.IsNullOrEmpty(username))
                return null;

            using (IceTeaEntities ite = new IceTeaEntities())
            {
                return ite.Users.Where(u => u.UserName == username).SingleOrDefault();
            }
        }

        /// <summary>
        /// Get Current Project Id of a specified user
        /// </summary>
        /// <param name="userId"></param>
        /// <returns></returns>
        public static int GetCurrentProjectId(int userId)
        {
            int curProjId = -1;
            using (IceTeaEntities ite = new IceTeaEntities())
            {
                int? pid = (from u in ite.Users where u.Id == userId select u.CurProdId).SingleOrDefault();
                if (pid.HasValue)
                    curProjId = pid.Value;
            }

            return curProjId;
        }

        /// <summary>
        /// Get current team id of a specified user
        /// </summary>
        /// <param name="userId"></param>
        /// <returns></returns>
        public static int GetCurrentTeamId(int userId)
        {
            int curTeamId = -1;
            using (IceTeaEntities ite = new IceTeaEntities())
            {
                int? tid = (from u in ite.Users where u.Id == userId select u.CurTeamId).SingleOrDefault();
                if (tid.HasValue)
                    curTeamId = tid.Value;
            }
            return curTeamId;
        }

        //looking for the Db to verify the user name is unique or not
        public static bool IsUserNameUnique(string username)
        {
            IceTeaEntities ite = new IceTeaEntities();
            return (from u in ite.Users
                    where u.UserName.Equals(username, StringComparison.OrdinalIgnoreCase)
                    select u).Count() <= 0;
        }

        //looking for the Db to verify the email is unique or not
        public static bool IsEmailUnique(string email)
        {
            IceTeaEntities ite = new IceTeaEntities();
            return (from u in ite.Users
                    where u.Email.Equals(email, StringComparison.OrdinalIgnoreCase)
                    select u).Count() <= 0;
        }
        #endregion

        

        #region Implements of IValidatableObject
        public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
        {
            List<ValidationResult> errors = new List<ValidationResult>();
            //validate user name unique
            if (!IsUserNameUnique(this.UserName))
            {
                errors.Add(new ValidationResult("The user name is already exist"));
            }
            //validate email is unique
            if (!IsEmailUnique(this.Email))
            {
                errors.Add(new ValidationResult("The Email is already exist"));
            }
            return errors;
        }
        #endregion
    }
}
